package com.nightpiter.controller.algorithms;

import static com.nightpiter.controller.log.Logger.log;
import static com.nightpiter.controller.log.Logger.logProfilerBegin;
import static com.nightpiter.controller.log.Logger.logProfilerEnd;

import java.util.ArrayList;
import java.util.Hashtable;

import com.nightpiter.model.MetroModel;
import com.nightpiter.model.objects.Station;
import com.nightpiter.model.objects.Transfer;
import com.nightpiter.model.objects.Tunnel;

/**
 * Graph class suitable to use with Dijkstra's shortest path algorithm
 * 
 * Package protected
 * 
 * @author Eldar Abusalimov (eldar.abusalimov@gmail.com)
 */
class Graph {

	/**
	 * array of vertices
	 */
	private Hashtable<Station, Vertex> verticesHash;

	/**
	 * public constructor
	 * 
	 * @param model
	 */
	public Graph(MetroModel model) {
		logProfilerBegin("create new Graph instance");

		logProfilerBegin("create Vertex for each station");
		ArrayList<Station> stations = model.getStations();
		this.verticesHash = new Hashtable<Station, Vertex>(stations.size(), 1);
		for (Station station : stations) {
			this.verticesHash.put(station, new Vertex(station));
		}
		logProfilerEnd("for each station cycle complete, totat vertices: "
				+ this.verticesHash.size());

		logProfilerBegin("create Edge for each transition");
		log("processing tunnels");
		ArrayList<Tunnel> tunnels = model.getTunnels();
		for (Tunnel tunnel : tunnels) {
			new Edge(tunnel, verticesHash.get(tunnel.getFromStation()),
					verticesHash.get(tunnel.getToStation()));
		}
		log("processing transfers");
		ArrayList<Transfer> transfers = model.getTransfers();
		for (Transfer transfer : transfers) {
			new Edge(transfer, verticesHash.get(transfer.getFromStation()),
					verticesHash.get(transfer.getToStation()));
		}
		logProfilerEnd("for each transition cycle complete");

		logProfilerEnd("graph contruct complete, totat vertices: "
				+ this.verticesHash.size());
	}

	/**
	 * prepares graph to the new calculation
	 * 
	 * @param station
	 *            the initial position
	 */
	public void reset() {
		for (Vertex vertex : this.verticesHash.values()) {
			vertex.reset();
		}
	}

	/**
	 * @return the vertices
	 */
	public Hashtable<Station, Vertex> getVerticesHash() {
		return verticesHash;
	}

}
